#include "func.h"
int recvn(int sockfd, void *buf, int length){
    int total = 0;
    char *p = (char *)buf;
    while(total < length){
        ssize_t sret = recv(sockfd, p+total, length-total, 0);
        total += sret;
    }
    return total;
}


int recvFile(int sockfd,char* bufc){

    //定义fileName字符数组来接收参数bufc的值
    char fileName[1024];
    strcpy(fileName,bufc);
    //用access函数来判断fileName是否存在
    int flag = access(fileName, F_OK); 
    //flag != 0文件不存在
    if(flag != 0)
    {
        //文件不存在所以要创建读写文件
        int fd = open(fileName, O_RDWR|O_CREAT, 0666);
        //声明小火车准备发送breakpoint相关信息给服务端
        train_t train;
        //初始化小火车
        memset(&train, 0, sizeof(train));
        //声明stat结构体statbuf准备获取文件大小
        //因为文件不存在所以获取的statbuf.st_size的值是0
        struct stat statbuf;
        //获取fileName的文件信息存到statbuf中
        stat(fileName,&statbuf);
        //初始化一个size来接收已有文件的字节数
        char size[1024];
        //将int类型的st_size,转成字符串放到size字符串数组里
        sprintf(size,"%d",(int)statbuf.st_size);
        //给小火车赋值
        //注意这里的length的值，是buf的长度
        train.length = strlen(size);
        //因为strlen不会算上‘\0’
        printf("这里的长度应该为1 ,train.length = %d\n",train.length);
        strcpy(train.data,size);
        //发送breakpoint信息给服务端
        send(sockfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);
        //接收文件长度
        int length;
        recvn(sockfd, &length, sizeof(length));
        recvn(sockfd, fileName, length);
        printf("客户端接收了文件名字,fileName = %s\n",fileName);
        //接收文件大小
        off_t filesize;
        recvn(sockfd, &length, sizeof(length));
        recvn(sockfd, &filesize, length);
        printf("客户端要接收的文件大小，filesize = %ld\n", filesize);

        //准备接收文件的内容
        //当前的cursize==0
        off_t cursize = statbuf.st_size;
        //test
        printf("当前的size大小：cursize=%ld\n",cursize);
        //调节进度条
        off_t slice = filesize/10000;
        //用于更新cursize
        off_t lastsize = 0;
        while(1){

            char buf[4096] = {0};

            recvn(sockfd, &length, sizeof(length));
            printf("准备接收服务端要发送的长度length= %d\n",length);
            //if(length != 1000){
              //  printf("length = %d\n", length);
            //}
            if(length == 0){
                break;
            }
            //接收length的字节放入buf
            recvn(sockfd, buf, length);
            //写入fd
            write(fd, buf, length);

            cursize += length;
            if(cursize - lastsize > slice){
                printf("%5.2lf%%\r",100.0*cursize/filesize);
                fflush(stdout);//将stdout缓冲区的数据刷到文件对象里面
                lastsize = cursize;
            }
        }
        printf("100.00%%\n");
        close(fd);
    }
    //这种情况文件存在
    else
    {
        //追加写法
        int fd = open(fileName, O_RDWR|O_APPEND, 0666);
        //声明小火车准备传给服务端已有文件的字节数
        train_t train;
        //初始化小火车
        memset(&train, 0, sizeof(train));

        struct stat statbuf;
        stat(fileName,&statbuf);

        char size[1024];
        sprintf(size,"%d",(int)statbuf.st_size);
        //test
        printf("获取的已有文件字节数为statbuf.st_size：%ld \n",statbuf.st_size);
        //test
        printf("由int类型转化成的字符串是bufi：%s\n",size);

        train.length = strlen(size);

        strcpy(train.data,size);

        send(sockfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);
        
        //接收文件长度
        int length;
        recvn(sockfd, &length, sizeof(length));
        recvn(sockfd, fileName, length);
        printf("客户端接收了文件名字,fileName = %s\n",fileName);
        //接收文件大小
        off_t filesize;
        recvn(sockfd, &length, sizeof(length));
        recvn(sockfd, &filesize, length);
        //printf("客户端还要接收文件大小，filesize = %ld\n", filesize);

        //准备接收文件的内容
        //当前的cursize==已有的文件字节数
        off_t cursize = statbuf.st_size;
        //test
        printf("当前的size大小：cursize=%ld\n",cursize);
        //调节进度条
        off_t slice = filesize/10000;
        //用于更新cursize
        off_t lastsize = 0;
        while(1){

            char buf[4096] = {0};

            recvn(sockfd, &length, sizeof(length));
            printf("准备接收服务端要发送的长度length= %d\n",length);
            //if(length != 1000){
              //  printf("length = %d\n", length);
            //}
            if(length == 0){
                break;
            }
            //接收length的字节放入buf
            recvn(sockfd, buf, length);
            //写入fd
            write(fd, buf, length);

            cursize += length;
            if(cursize - lastsize > slice){
                printf("%5.2lf%%\r",100.0*cursize/filesize);
                fflush(stdout);//将stdout缓冲区的数据刷到文件对象里面
                lastsize = cursize;
            }
        }
        printf("100.00%%\n");
        close(fd);
    }
    return 0;
}

int putsFile(int sockfd, const char *filename)
{
    train_t train;
    memset(&train, 0, sizeof(train));
    train.length = strlen(filename);
    strcpy(train.data, filename);
    send(sockfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);

    int fd = open(filename, O_RDWR);

    struct stat statbuf;
    fstat(fd,&statbuf);

    train.length = sizeof(statbuf.st_size);
    memcpy(train.data,&statbuf.st_size,train.length);
    send(sockfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);

    char *p = (char *)mmap(NULL,statbuf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    ERROR_CHECK(p,MAP_FAILED,"mmap");

    off_t totalsize = 0;

    while(totalsize < statbuf.st_size)
    {
        if(statbuf.st_size>1000)
        {
            train.length = 1000;
        }
        else
        {
            train.length = statbuf.st_size-totalsize;
        }
        send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        send(sockfd,p+totalsize,train.length,MSG_NOSIGNAL);
        totalsize += train.length;
    }
    train.length = 0;
    send(sockfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
    munmap(p,statbuf.st_size);
    close(fd);
    return 0;
}

